/** ***********************************************************************************
* @file         battery_task.c
* @brief        备用电池充电管理任务
* @details      主要用来对锂电池进行充放电管理
* @author       杨小珛
* @date         2021/03/18
* @copyright    北京高知科技有限公司    
* @version      V1.0
* @attention    无
**************************************************************************************/
#include "battery_task.h"
#include "mon_task.h"
#include "log_task.h"
#include "power_task.h"
#include "port_task.h"
#include "com_lib.h"

battery_charg_state_e battery_charg_state;
battery_discharg_state_e battery_discharg_state;
battery_insta_state_e battery_insta_state;

volatile uint32_t battery_delay_charge_time;		    /*电池充电延时寄存器*/
volatile uint32_t battery_delay_discharge_time;	    /*电池放电延时寄存器*/
volatile uint8_t battery_power_man_id;                /*电源管理ID*/

static void battery_handle_task( void * pvParameters );
static void battery_charge_port_init(void);
static void battery_charge_en_control( battery_charge_control_e state );
static void battery_voltage_get( uint32_t *vol );
static void battery_charg_management( void );
static uint32_t battery_discharg_management( void );

static uint32_t battery_task_into_run_mode(void);
static uint32_t battery_task_into_sleep_mode(void);
static uint32_t battery_task_into_stop_mode(void);

/** ****************************************************************************
* @remarks       void battery_man_create_task( unsigned portBASE_TYPE uxPriority )
* @brief         备用电池管理
* @param[in]     uxPriority任务优先级；
* @param[out]    无
* @return        无
* @attention     在系统启动后进行创建
*******************************************************************************/
void battery_man_create_task( unsigned portBASE_TYPE uxPriority )
{   
    battery_charg_state = BAT_CHARG_INIT;
    battery_discharg_state = BAT_DISCHARD_INIT;
    battery_insta_state = BAT_INSTA_INIT;
    battery_charge_port_init();
    gaoz_thread_create(battery_handle_task, BAT_MAN_NAME, 1024*2, NULL, uxPriority);
}

/** ****************************************************************************
* @remarks       void battery_charge_port_init(void)
* @brief         初始化系统锂电池充电使能IO口
* @param[in]     无
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void battery_charge_port_init(void)
{
    gaoz_gpio_pull_disable( BATTERY_CHARGE_PIN );
    gaoz_gpio_mode_set( BATTERY_CHARGE_PIN,0 );
    gaoz_gpio_cfg( BATTERY_CHARGE_PIN,1 );
    gaoz_gpio_set( BATTERY_CHARGE_PIN,0 );
}   

/** ****************************************************************************
* @remarks       void battery_charge_en_control( battery_charge_control_e state )
* @brief         备用电池充电使能开关
* @param[in]     state :CHARGE_ON 充电使能 ，CHARGE_OFF 充电失能
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void battery_charge_en_control( battery_charge_control_e state )
{
	if( state == CHARGE_ON )
	{
        gaoz_gpio_set( BATTERY_CHARGE_PIN,1 );
	}
	else if( state == CHARGE_OFF )
	{
        gaoz_gpio_set( BATTERY_CHARGE_PIN,0 );
	}
}

/** ****************************************************************************
* @remarks       static void battery_voltage_get( uint32_t *vol )
* @brief         获取备用电池电压
* @param[in]     无
* @param[out]    *vol 电压值
* @return        无
* @attention     无
*******************************************************************************/
static void battery_voltage_get( uint32_t *vol )
{
    *vol = port_adc_gpio_value_get( GET_ADC1 ) * 3;
}

/** ****************************************************************************
* @remarks       battery_charg_state_e battery_charg_state_get( void )
* @brief         获取系统备用电池充电状态
* @param[in]     无
* @param[out]    无
* @return        充电状态
* @attention     无
*******************************************************************************/
battery_charg_state_e battery_charg_state_get( void )
{
    return battery_charg_state;
}

/** ****************************************************************************
* @remarks       battery_discharg_state_e battery_discharg_state_get( void )
* @brief         获取系统备用电池放电状态
* @param[in]     无
* @param[out]    无
* @return        充电状态
* @attention     无
*******************************************************************************/
battery_discharg_state_e battery_discharg_state_get( void )
{
    return battery_discharg_state;
}

/** ****************************************************************************
* @remarks       battery_insta_state_e battery_insta_state_get( void )
* @brief         获取系统备用电池安装的状态
* @param[in]     无
* @param[out]    无
* @return        充电状态
* @attention     无
*******************************************************************************/
battery_insta_state_e battery_insta_state_get( void )
{
    return battery_insta_state;
}

/** ****************************************************************************
* @remarks       static void battery_charg_management( void )
* @brief         系统备用电池充电管理
* @param[in]     无
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void battery_charg_management( void )
{
	uint32_t chage_vol_on = 0 , chage_vol_off = 0;
	switch( battery_charg_state )
	{
		case BAT_CHARG_INIT: 		                 /*备用电池初始化，检测电池是否已经安装*/
			battery_discharg_state = BAT_DISCHARD_INIT;
			battery_charge_en_control( CHARGE_OFF );
			gaoz_task_sleep(100);
            battery_voltage_get( &chage_vol_off );
            battery_charge_en_control( CHARGE_ON );
			gaoz_task_sleep(100);
			battery_voltage_get( &chage_vol_on ); 
			if( calculated_absolute_value (chage_vol_on, chage_vol_off) < 100 )
			{   
				battery_charg_state = BAT_CHARG_YES;
                battery_insta_state = BAT_INSTA_YES;
			}
			else
			{
				battery_charg_state = BAT_CHARG_NO;
                battery_insta_state = BAT_INSTA_NO;
			}
		break;
		case BAT_CHARG_START:						  /*备份电池开始充电*/
			battery_charge_en_control( CHARGE_ON ); /*充电使能*/
			battery_voltage_get( &chage_vol_on );    /*检测备用电池电量是否符合预设阀值*/
			if( chage_vol_on > BATTERY_CHARGE_MAX_VOLTAGE )
			{
				battery_charg_state = BAT_CHARG_DELAY;
				battery_delay_charge_time = gaoz_get_systick(); /*获取当前最新的系统时钟*/
			}
			if( pdPASS == sys_timestamp_delay(( uint32_t* )&battery_delay_charge_time, BATTERY_DELAY_DISCHARGE_60SEC  ) )
			{
                battery_charg_state = BAT_CHARG_INIT;
			}
		break;
		case BAT_CHARG_DELAY:						  /*备份电池延时充电*/
			if( pdPASS == sys_timestamp_delay(( uint32_t* )&battery_delay_charge_time, BATTERY_DELAY_CHARGE_TIME  ) )
			{
				battery_charg_state = BAT_CHARG_STOP;
                log_debug_send(DEBUG_MODE,BAT_MAN_NAME ,"Battery management task stop charging\r\n",0);
			}
		break;	
		case BAT_CHARG_STOP:						/*备份电池开始充电*/
			battery_charge_en_control( CHARGE_OFF );
			battery_voltage_get( &chage_vol_off );
			if( chage_vol_off < BATTERY_CHARGE_MIN_VOLTAGE )
			{
				battery_charg_state = BAT_CHARG_INIT;
			}
		break;
		case BAT_CHARG_YES: 				        /*备用电池已安装*/
			battery_charg_state = BAT_CHARG_START;
            battery_delay_charge_time = gaoz_get_systick(); /*获取当前最新的系统时钟*/
            log_debug_send(DEBUG_MODE,BAT_MAN_NAME ,"Battery management task start charging\r\n",0);
		break;
		case BAT_CHARG_NO: 				            /*备用电池未安装*/
			battery_charg_state = BAT_CHARG_INIT; 
		break;
	}
}

/** ****************************************************************************
* @remarks       static uint32_t battery_discharg_management( void )
* @brief         系统备用电池管理
* @param[in]     无
* @param[out]    无
* @return        pdPASS 成功  pdFAIL 失败
* @attention     无
*******************************************************************************/
static uint32_t battery_discharg_management( void )
{	
	uint32_t ret = pdFAIL, dischage_vol= 0;
	switch( battery_discharg_state )
	{
		case BAT_DISCHARD_INIT:                                         /*检测系统电源状态，系统电源断电*/
            battery_charge_en_control( CHARGE_OFF );
			battery_charg_state = BAT_CHARG_INIT;
			if( sys_hard_state_get( SYS_POWER ) ==  SYS_POWER_OFF )     /* 获取车辆主电源的状态 */
			{
				battery_discharg_state = BAT_DISCHARD_START;
				battery_delay_discharge_time = gaoz_get_systick();	    /* 重新刷新心跳周期时间*/
			}
			else
			{
				battery_discharg_state = BAT_DISCHARD_STOP;
			}
		break;
		case BAT_DISCHARD_START:
			battery_voltage_get( &dischage_vol );
			if( dischage_vol < BATTERY_CHARGE_MIN_VOLTAGE )
			{
				battery_discharg_state = BAT_DISCHARD_DELAY;
				battery_delay_discharge_time = gaoz_get_systick(); /*重新刷新心跳周期时间*/
			}
			else
			{
				if( pdPASS == sys_timestamp_delay(( uint32_t* )&battery_delay_discharge_time, BATTERY_DELAY_DISCHARGE_60SEC  ) )
				{		
					battery_discharg_state = BAT_DISCHARD_STOP;
				}
			}
		break;
		case BAT_DISCHARD_DELAY:
            #if 0
			if( pdPASS == sys_timestamp_delay(( uint32_t* )&battery_delay_discharge_time, BATTERY_DELAY_DISCHARGE_3SEC  ) )
			{					
				battery_discharg_state = BAT_DISCHARD_STOP;
			}
            #else
            battery_discharg_state = BAT_DISCHARD_STOP;
            #endif
		break;	
		case BAT_DISCHARD_STOP:
			ret = pdPASS;
		break;
	}
	return ret;
}

/** ****************************************************************************
* @remarks       static uint32_t battery_task_into_run_mode(void)
* @brief         BAT任务进入运行状态
* @param[in]     无
* @param[out]    无
* @return        pdPASS 设置成功 pdFAIL 设置失败
* @attention     无
*******************************************************************************/
static uint32_t battery_task_into_run_mode(void)
{
    task_modules_e state = TASK_MODE_INIT;
    uint32_t ret = pdFAIL;
    state = power_man_save_state_get( battery_power_man_id ); /*获取任务的运行状态*/
    if( state != TASK_RUN_MODE )
    {   
        power_man_save_state_set( battery_power_man_id ,TASK_RUN_MODE );
        log_debug_send(INFOR_MODE,BAT_MAN_NAME ,"<<<<<<<<<<*****BAT task enters RUN mode*****>>>>>>>>>>\r\n", 0);
        ret = pdPASS;
    }
    else if( state == TASK_RUN_MODE )
    {
        ret = pdPASS;
    }
    return ret;
}
/** ****************************************************************************
* @remarks       static uint32_t battery_task_into_sleep_mode(void)
* @brief         BAT任务进入睡眠状态
* @param[in]     无
* @param[out]    无
* @return        pdPASS 设置成功 pdFAIL 设置失败
* @attention     无
*******************************************************************************/
static uint32_t battery_task_into_sleep_mode(void)
{
    task_modules_e state = TASK_MODE_INIT;
    uint32_t ret = pdFAIL; 
    state = power_man_save_state_get( battery_power_man_id ); /*获取任务的运行状态*/
    if( state != TASK_SLEEP_MODE )
    {   
        power_man_save_state_set( battery_power_man_id ,TASK_SLEEP_MODE );
        log_debug_send(INFOR_MODE,BAT_MAN_NAME ,"<<<<<<<<<<*****BAT task enters SLEEP mode*****>>>>>>>>>>\r\n", 0);
        ret = pdPASS;
    }
    else if( state == TASK_SLEEP_MODE )
    {
        ret = pdPASS;
    }
    return ret;
}
/** ****************************************************************************
* @remarks       static uint32_t battery_task_into_stop_mode(void)
* @brief         BAT任务进入停止状态
* @param[in]     无
* @param[out]    无
* @return        pdPASS 设置成功 pdFAIL 设置失败
* @attention     无
*******************************************************************************/
static uint32_t battery_task_into_stop_mode(void)
{
    task_modules_e state = TASK_MODE_INIT;
    uint32_t ret = pdFAIL; 
    state = power_man_save_state_get( battery_power_man_id ); /*获取任务的运行状态*/
    if( state != TASK_STOP_MODE )
    {   
        power_man_save_state_set( battery_power_man_id ,TASK_STOP_MODE );
        log_debug_send(INFOR_MODE,BAT_MAN_NAME ,"<<<<<<<<<<*****BAT task enters STOP mode*****>>>>>>>>>>\r\n", 0);
        ret = pdPASS;
    }
    else if( state == TASK_STOP_MODE )
    {
        ret = pdPASS;
    }
    return ret;
}

/** ****************************************************************************
* @remarks       static void battery_handle_task( void * pvParameters )
* @brief         备用电池充电管理处理任务
* @param[in]     * pvParameters 任务参数
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
static void battery_handle_task( void * pvParameters )
{
    ( void ) pvParameters;
    task_modules_e bat_run_st;
    mon_reg_task_dog( 60 * GAOZ_TICK_PERIOD_S ,(uint8_t *)BAT_MAN_NAME , TASK_SEM_YES ); /*注册任务看门狗*/
    power_man_task_reg((uint8_t * )BAT_MAN_NAME,(uint8_t *)&battery_power_man_id ); /*注册系统电源管理*/
    log_debug_send(DEBUG_MODE,BAT_MAN_NAME ,"Battery management task started successfully\r\n",0);
    for( ;; )
    {   
        mon_reset_task_dog();
        bat_run_st = power_man_task_state_get( battery_power_man_id );      /*获取任务运行的状态*/
        /*******************************BAT任务处于运行状态***********************************/
        if(  bat_run_st == TASK_RUN_MODE )                                  /*任务进入全速运行模式*/
        {
			if( battery_task_into_run_mode() != pdPASS )                    /*判断睡眠是否设置成功，没有设置成功进入延时*/
			{
				gaoz_task_sleep(1000);
				continue;
			}
            battery_charg_management();
            gaoz_task_sleep( 1000 );
        }
        /*******************************BAT任务处于休眠状态************************************/
        else if(  bat_run_st == TASK_SLEEP_MODE )                           /*任务进入睡眠模式*/
        {
            if( battery_discharg_management() == pdPASS )                   
            {
                if( battery_task_into_sleep_mode() == pdPASS )              /*判断任务任务是否进入睡眠模式，进入睡眠模式后进行长时间延时*/ 
                {
                    gaoz_task_sleep( 1000 );
                    continue;
                }
            }
            gaoz_task_sleep( 1000 );
        }
        /*******************************BAT任务处于停止状态************************************/
        else if(  bat_run_st == TASK_STOP_MODE )                            /*任务进入睡眠模式*/
        {
            if( battery_discharg_management() == pdPASS )   
            {
                if( battery_task_into_stop_mode() ==  pdPASS )              /*判断任务任务是否进入停止模式，进入停止模式后进行长时间延时*/ 
                {
                    gaoz_task_sleep( 1000 );
                    continue;
                }
            }
            gaoz_task_sleep( 1000 );
        }
        /*******************************BAT任务空循环状态************************************/
        else                                      
        {
            gaoz_task_sleep( 100 );
        }
    }
}

